#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <stdint.h>

#include <net/if.h>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>

#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/can/error.h>

#include <iostream>
#include <list>

#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "can_app.h"
#include "can_uim.h"
#include "board_data_proc.h"
#include "common.h"
#include "msg_def.h"

#include "procedure.h"
#include "tecan.h"

extern ob_manage * g_ptrObManage;

pthread_mutex_t mutex_recvBuff; 
eleInfoOnBoard eleOnBoardArr[MAX_NUM_ELE_ON_ELE_BOARD] = {
    {
        .portNum = 0,
        .currPos = 0,
        .posToMove = 0,
        .max_distance = 120000,
        .thetaPerStep = 1.8,
        .lead = 12,
        .msgSrc = 0,
    },
    {
        .portNum = 1,
        .currPos = 0,
        .posToMove = 0,
        .max_distance = 120000,
        .thetaPerStep = 1.8,
        .lead = 12,
        .msgSrc = 0,
        
    },
    {
        .portNum = 2,
        .currPos = 0,
        .posToMove = 0,
        .max_distance = 3000,
        .thetaPerStep = 1.8,
        .lead = 12,
        .msgSrc = 0,
        
    },
    {
        .portNum = 3,
        .currPos = 0,
        .posToMove = 0,
        .max_distance = 3000,
        .thetaPerStep = 1.8,
        .lead = 12,
        .msgSrc = 0,
        
    },

};


CCan::CCan()
{
	m_recvFrameBuff.clear();
    m_ExitThreadFlag = 0;
    m_MQ_type = 1;
    //for test
    fd_data_temp = open("/home/root/tempData.txt",O_RDWR);
    lenInStr = 0;
    numData = 0;
    if(fd_data_temp==-1)
    {
        printf("open file for storring temp failed\n");
    }
    else
    {
        printf("open file for storring temp success\n");
        /* code */
    }
        
}

CCan::~CCan()
{
    if(m_ExitThreadFlag==0)
    {
        m_ExitThreadFlag = 1;
    }
}

int  CCan::OpenCanPort( int portNum,filter_array * filtersIn )
{
    struct sockaddr_can addr;
    struct ifreq ifr;
    pthread_attr_t 		attr;
    int res;
    int ro = 0; //receive msg self send, 0: close, 1:open
    
    memset(m_portName,0,MAX_NAME_LEN);

    m_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    sprintf(m_portName,"%s%d","can",portNum);
    strcpy(ifr.ifr_name, m_portName );


    ioctl(m_fd, SIOCGIFINDEX, &ifr);
    
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    bind(m_fd, (struct sockaddr *)&addr, sizeof(addr));

    if(filtersIn&&filtersIn->num)
    {
        setsockopt(m_fd, SOL_CAN_RAW, CAN_RAW_FILTER, filtersIn->filters, sizeof(struct can_filter)*(filtersIn->num));
    }

    
    setsockopt(m_fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &ro, sizeof(ro));

    

    res = pthread_attr_init(&attr);
    if( res!=0 )
	{
		printf("Create attribute failed\n" );
	}

    res = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );

	res += pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
	if( res!=0 )
	{
		printf( "Setting attribute failed\n" );
	}

	res = pthread_create( &m_thread_recv, &attr, (void *(*) (void *))&CanReceiveThreadFunc, (void*)this );
	if( res!=0 )
	{
		CloseCanPort();
		return -1;
	}

    res = pthread_create( &m_thread_proc, &attr, (void *(*) (void *))&CanDataProcThreadFunc, (void*)this );
    if( res!=0 )
	{
		CloseCanPort();
		return -1;
	}
    printf("open %s success,m_fd[%d]\n",m_portName,m_fd);
	pthread_attr_destroy( &attr );
    return 0;
}

int  CCan::CloseCanPort( )
{
    m_ExitThreadFlag = 1;
    sleep(1);
    if(m_fd!=-1)
    {
       close(m_fd); 
    }

    clearData();

    if(fd_data_temp!=-1)
    {
        close(fd_data_temp);
        fd_data_temp = -1;
    }
    
}

int  CCan::WriteCanPort( struct can_frame * frameIn)
{
    int sendBytes = write(m_fd, frameIn, sizeof(struct can_frame));
    
    //printf("sid:%08x,dlc:%d\n",frameIn->can_id,frameIn->can_dlc);

    if(sendBytes>0)
    {
        //printf("send to can interface success!\n");
        return sendBytes;
    }
    else
    {
        char errorPrefix[32];
        sprintf(errorPrefix,"write %s:",m_portName);
        perror(errorPrefix);
        usleep(200);
        write(m_fd, frameIn, sizeof(struct can_frame));
        return -1;
    }
}

int CCan::sendString(unsigned short sid, int len, unsigned char * buff)
{
    int sizeLeft = len;
    struct can_frame frameToSend;
    unsigned char * ptrData = buff;

    frameToSend.can_id = sid;
    int ret = 0;
    int sendBytes = 0;

    while(sizeLeft>0)
    {
        if(sizeLeft>=8)
        {
            frameToSend.can_dlc = 8;
            memcpy(frameToSend.data,ptrData,8);
            ptrData += 8;
            sizeLeft-=8;
            ret = this->WriteCanPort(&frameToSend);

            if(ret>0)
            {
               sendBytes+= frameToSend.can_dlc;
            }
            else
            {
                return sendBytes;
            }
        }
        else 
        {
            frameToSend.can_dlc = sizeLeft;
            memcpy(frameToSend.data,ptrData,sizeLeft);
            ptrData += sizeLeft;
            sizeLeft-=sizeLeft;
            ret = this->WriteCanPort(&frameToSend);
            if(ret>0)
            {
               sendBytes+= frameToSend.can_dlc;
            }
            else
            {
                return sendBytes;
            }
        }

        usleep(5000);
    }

    return sendBytes;
}

int CCan::CanReceiveThreadFunc( void* lparam )
{
    CCan *pCan = (CCan*)lparam;
    fd_set fdRead;
	int ret;
	struct timeval	aTime;
    struct can_frame tmpFrame;
    int nbytes = 0;

    printf("enter CanReceiveThreadFunc,m_fd[%d]\n",pCan->m_fd);
    initTempReportCtl();
    while( 1 )
	{
		if( pCan->m_ExitThreadFlag )
		{
			break;
		}

		FD_ZERO(&fdRead);
		FD_SET(pCan->m_fd,&fdRead);

		aTime.tv_sec = 0;
		aTime.tv_usec = 300000;

		ret = select( pCan->m_fd+1,&fdRead,NULL,NULL,&aTime );
		//printf( "select ret = %d\n", ret);

		if (ret < 0 )
		{
			pCan->CloseCanPort( );
			break;
		}

		if (ret > 0)
		{
			if (FD_ISSET(pCan->m_fd,&fdRead))
			{
				//data available, so get it!
				if((nbytes = read(pCan->m_fd, &tmpFrame, sizeof(struct can_frame))) < 0)
                {
                    printf("read can port failed\n");
                    break;
                }
                else
                {
#if _DEBUG_LOG
                    printf("recv can data,m_fd[%d],len[%d]\n",pCan->m_fd,nbytes);
#endif
                    pthread_mutex_lock(&mutex_recvBuff);  
                    pCan->m_recvFrameBuff.push_back(tmpFrame);
                    pthread_mutex_unlock(&mutex_recvBuff);
                }
			}
		}
	}

	printf( "ReceiveThreadFunc finished\n");
	//pthread_exit( NULL );
	return 0;
}

int CCan::PackagePro( void * frameIn )
{
    struct can_frame * frame = (struct can_frame *)frameIn;
    //printf("int PackagePro, canid is <0x%03x>, dlc is %d\n",frame->can_id & CAN_SFF_MASK,frame->can_dlc); 
    int len = frame->can_dlc;
    board_frame boardFrame; 
    
    char * ptrDataOut = NULL;

#define MAX_DATA_SIZE 256

#if _DEBUG_LOG
    printf("data:");
    for(int i=0;i<len;i++)
    {
        printf("%02x,",frame->data[i]);
    }
#endif
    // printf("\n");
    if(frame->can_dlc >= 2)
    {
        boardFrame.boardId = frame->data[0];
        //boardFrame.dataType = frame->data[1];
#if _DEBUG_LOG
        printf("boardId:%02x\n",boardFrame.boardId);
#endif
        //printf("before new\n");
        try{

            ptrDataOut = new char[MAX_DATA_SIZE];
        }
        catch(const std::bad_alloc& e)
        {
            printf("new memory failed\n");
            return 1;
        }
        //printf("after new\n");
        
        memset(ptrDataOut,0,MAX_DATA_SIZE);
        // if(boardFrame.boardId == 3)
        // {
        //     ptrDataOut = (void*)&frameRet;
        //     memset(ptrDataOut,0,sizeof(struct can_frame));
        // }
        //printf("after memset\n");
        if(boardFrame.boardId>0 && boardFrame.boardId<MAX_BOARD_NUM)
        {
            if(func_data_proc[boardFrame.boardId - 1])
            {
                //printf("call proc func,frame:%08x\n",frame);
                //printf("call proc func func:%08x\n",func_data_proc[boardFrame.boardId - 1]);
                func_data_proc[boardFrame.boardId - 1](frame->can_dlc-1,&(frame->data[1]),ptrDataOut);
            }
            
        }

        switch (boardFrame.boardId)
        {
            case CAP_DETECT_BOARD:
            {
                struct can_frame * pstframeRet = (struct can_frame *)ptrDataOut;
                if(pstframeRet->can_dlc>0)
                {
                    pstframeRet->can_id = 0x300 + boardFrame.boardId;
                    printf("send to can_id[%03x],dlc[%d]\n",
                    pstframeRet->can_id,pstframeRet->can_dlc);
                    this->WriteCanPort(pstframeRet);
                }            
            }
            break;

            case ELE_CTL_BOARD:
            {
                recvDataEleCtl * pstCheckData = (recvDataEleCtl *)ptrDataOut;
                if(pstCheckData->sid >= 80 && pstCheckData->sid <= 83)
                {
                    if(g_ptrObManage!=NULL)
                    {
                        printf("update for sid[%d]\n",pstCheckData->sid);
                        g_ptrObManage->update(pstCheckData);
                    }
                    if(eleOnBoardArr[pstCheckData->sid-80].msgSrc == MSG_FROM_LUA)
                    {
                        sendAckToLua(pstCheckData);
                    }
                    if(pstCheckData->frameType == CHECK_MOVE_END)
                    {
                        eleOnBoardArr[pstCheckData->sid-80].currPos += eleOnBoardArr[pstCheckData->sid-80].posToMove;
                    }
                     
                }
            }
            break;

            case SYSTEM_CTRL_BOARD:
            {
                recvDataEleCtl * pstCheckData = (recvDataEleCtl *)ptrDataOut;
                if(pstCheckData->sid >= 84 && pstCheckData->sid <= 87)
                {
                    if(g_ptrObManage!=NULL)
                    {
                        printf("update for sid[%d]\n",pstCheckData->sid);
                        g_ptrObManage->update(pstCheckData);
                    }
                }
            }
            break;

            default:
            break;

        }
        
        if(ptrDataOut)
        {
            delete [] ptrDataOut;
            ptrDataOut = NULL;
        }
        
        
    }
    

}

void CCan::cmdAct(void * param)
{
    ctl_uim * ctlFrame =  (ctl_uim *)param;
    
    struct can_frame canFrame;
    memset(&canFrame,0,sizeof(struct can_frame));

    canFrame.can_id = (0x0300 | (ctlFrame->sid & 0x000f));

    //printf("in CCan::cmdAct,sid:%d\n",ctlFrame->sid);

    switch (ctlFrame->sid)
    {
#ifndef _QPCR
        case ELE_CTL_BOARD:
        {
            if(ctlFrame->sid==ELE_CTL_BOARD)
            {
                //process for electronic control board
        #if INCREMENT_POS

                canFrame.data[0] = 0x0f&ctlFrame->opcode;
                canFrame.data[0] |= (((ctlFrame->un_cmd.moveCtl.ele_index) << 4)&0xf0);
                if(ctlFrame->opcode == MOVE)
                {
                    canFrame.can_dlc = 6;

                    canFrame.data[1] = ctlFrame->un_cmd.moveCtl.dir;
                    canFrame.data[2] = ctlFrame->un_cmd.moveCtl.position&0x00ff;
                    canFrame.data[3] = (ctlFrame->un_cmd.moveCtl.position>>8)&0x00ff;
                    canFrame.data[4] = (ctlFrame->un_cmd.moveCtl.position>>16)&0x00ff;
                    canFrame.data[5] = (ctlFrame->un_cmd.moveCtl.position>>24)&0x00ff;
                }
                else
                {
                    /* code */
                    canFrame.can_dlc = 1;
                }
        #else
                unsigned char eleIndex = ctlFrame->un_cmd.moveCtl.ele_index;
                if(eleIndex>=MAX_NUM_ELE_ON_ELE_BOARD)
                {
                    return;
                }
                eleOnBoardArr[eleIndex].msgSrc = ctlFrame->msgSrc;
                printf("ele:%d,opcode:%d,pos:%d\n",eleIndex,ctlFrame->opcode,
                       ctlFrame->un_cmd.moveCtl.position);
                if(ctlFrame->opcode == MOVE || ctlFrame->opcode == MOVE_MM)
                {
                    if(ctlFrame->opcode == MOVE_MM)
                    {
                        ctlFrame->un_cmd.moveCtl.position = mm_to_steps(ctlFrame->un_cmd.moveCtl_mm.position,
                        16,eleOnBoardArr[eleIndex].lead,1.8);

                        ctlFrame->un_cmd.moveCtl.inc_speed = mm_to_steps(ctlFrame->un_cmd.moveCtl_mm.inc_speed,
                        16,eleOnBoardArr[eleIndex].lead,1.8);

                        ctlFrame->un_cmd.moveCtl.dec_speed = mm_to_steps(ctlFrame->un_cmd.moveCtl_mm.dec_speed,
                        16,eleOnBoardArr[eleIndex].lead,1.8);

                        ctlFrame->un_cmd.moveCtl.speed = mm_to_steps(ctlFrame->un_cmd.moveCtl_mm.speed,
                        16,eleOnBoardArr[eleIndex].lead,1.8);
                    }
                    if(ctlFrame->un_cmd.moveCtl.position == 0)
                    {
                        canFrame.data[0] = 0x0f&RET_BACK;
                        canFrame.can_dlc = 1; 
                        eleOnBoardArr[eleIndex].currPos = 0;           
                    }
                    else
                    {
                        canFrame.data[0] = 0x0f&MOVE; 
                        int curPos = eleOnBoardArr[eleIndex].currPos;
                        unsigned int tempPos = 0;

                        if(curPos == ctlFrame->un_cmd.moveCtl.position)
                        {
                            //no need to move,here                           

                            recvDataEleCtl stCheckData;
                            stCheckData.sid = 80+eleIndex;
                            stCheckData.frameType = CHECK_MOVE_END;
                            printf("no need to move for sid[%d]\n",stCheckData.sid);
                            
                            if(eleOnBoardArr[eleIndex].msgSrc == MSG_FROM_LUA)
                            {
                                sendAckToLua(&stCheckData);
                            }
                            else
                            {
                                msgQueueAck stMsgQueueAck;
                                memset(&stMsgQueueAck,0,sizeof(msgQueueAck));
                                stMsgQueueAck.type = QUEUE_MSG_TYPE_GRPC;
                                stMsgQueueAck.msg.statusCode = 0;
                                stMsgQueueAck.msg.errorNum = 0;
                                stMsgQueueAck.msg.sid = 80+eleIndex;
                                stMsgQueueAck.msg.moduleId = -1;
                                if(msgsnd(this->getKeyId_FrameMQ(), (void*)&stMsgQueueAck, sizeof(msgAck), 0) < 0)
                                {
                                        printf("send ack failed\n");
                                }
                            }
                            if(g_ptrObManage!=NULL)
                            {
                                printf("update for sid[%d]\n",stCheckData.sid);
                                
                                g_ptrObManage->update(&stCheckData);
                            }

                            return;
                        }
                        else if(curPos > ctlFrame->un_cmd.moveCtl.position)
                        {
                            canFrame.data[1] = 1;//set dir to 0;
                            tempPos = curPos - ctlFrame->un_cmd.moveCtl.position;
                        }
                        else
                        {
                            canFrame.data[1] = 0;//set dir to 1;
                            tempPos = ctlFrame->un_cmd.moveCtl.position - curPos;
                            /* code */
                        }

                        canFrame.can_dlc = 6;
                        canFrame.data[2] = tempPos&0x00ff;
                        canFrame.data[3] = (tempPos>>8)&0x00ff;
                        canFrame.data[4] = (tempPos>>16)&0x00ff;
                        canFrame.data[5] = (tempPos>>24)&0x00ff;

                        //refresh the position of the ele ctl
                        //printf("eleIndex:%d,dlc:%d,pos:%d,dir:%d\n",eleIndex,canFrame.can_dlc,
                        //tempPos,canFrame.data[1]);
                        //eleOnBoardArr[eleIndex].currPos = ctlFrame->un_cmd.moveCtl.position;
                        eleOnBoardArr[eleIndex].posToMove = ctlFrame->un_cmd.moveCtl.position - eleOnBoardArr[eleIndex].currPos;       
                        //eleOnBoardArr[eleIndex].currPos = ctlFrame->un_cmd.moveCtl.position;
                    }
                    canFrame.data[0] |= (((eleIndex) << 4)&0xf0);

                }
                else
                {
                    canFrame.data[0] = 0x0f&ctlFrame->opcode;
                    canFrame.data[0] |= (((ctlFrame->un_cmd.moveCtl.ele_index) << 4)&0xf0);
                    canFrame.can_dlc = 1;

                    if(ctlFrame->opcode==RET_BACK)
                    {
                        eleOnBoardArr[eleIndex].currPos = 0;
                    }
                    
                }
        #endif
            }
        
        }
        break;
        case IO_EXPAND_BOARD:
        {
            printf("IO_EXPAND_BOARD,opcode:%d\n",ctlFrame->opcode);
            
            if(ctlFrame->opcode == SYSCTL_LIQUID)
            {
                djLiquidCtl * pstDjClenCtl = &(ctlFrame->un_cmd.djLiquidParam);
                //printf("cmd of io ctl board recv, opcode[%d],chan[%d]\n",ctlFrame->opcode,pstDjClenCtl->chanNum);
                int tempChanNum = pstDjClenCtl->chanNum;
                if(tempChanNum&0x00f0)
                {
                    tempChanNum = tempChanNum - 16 + 6;
                }
                if(tempChanNum >= 12)
                {
                    return;
                }
                io_board_msg_src_dj[tempChanNum] = ctlFrame->msgSrc;
                unsigned char opCode = (pstDjClenCtl->paramType == 1)?CENTRE_START:CENTRE_STOP;

                encap_io_expand_gram(opCode,pstDjClenCtl->chanNum,ctlFrame->opcode,&(pstDjClenCtl->duration),&canFrame);
            }
            else if(ctlFrame->opcode == DRAWER_LOCK)
            {
                drawer_lock_param * pstDrawerLock = &(ctlFrame->un_cmd.drawerLockParam);
                printf("cmd of io ctl board recv, opcode[%d],chan[%d]\n",ctlFrame->opcode,pstDrawerLock->drawerId);
                int tempChanNum = pstDrawerLock->drawerId;
                io_board_msg_src_drawer[tempChanNum] = ctlFrame->msgSrc;
                unsigned char opCode = (pstDrawerLock->isToLock == 1)?CENTRE_START:CENTRE_STOP;

                encap_io_expand_gram(opCode,pstDrawerLock->drawerId,ctlFrame->opcode,NULL,&canFrame);
            }
            
        }
        break;
        case CAP_DETECT_BOARD:
        {
            capCtl * ptrCtlData = &(ctlFrame->un_cmd.capCtlData);
            if(  ptrCtlData->paramType == CAP_DELATA_ENV_LIQUID
              || ptrCtlData->paramType == CAP_DELATA_ENV_SUCK
              )
              {
                  encap_cap_gram(ctlFrame->opcode,ptrCtlData->chanMask,
                  ptrCtlData->paramType,&(ptrCtlData->delta),&canFrame);
              }
              else
              {
                  encap_cap_gram(ctlFrame->opcode,ptrCtlData->chanMask,
                  ptrCtlData->paramType,NULL,&canFrame);
              }
            
        }
        break;
        case PURIFICATION_BOARD:
        {
            printf("PURIFICATION_BOARD,op:%d\n",ctlFrame->opcode);
            if(ctlFrame->opcode == HEAT_CTL)
            {
                heatParam * ptrHeatParam = &(ctlFrame->un_cmd.heatCtlData);
                if(ptrHeatParam->chan >= MAX_PID_NUM)
                {
                    return;
                }
                printf("PURIFICATION_BOARD,op:%d,temperature:%f\n",ptrHeatParam->opcode,ptrHeatParam->temperature);
                purify_board_msg_src_heat[ptrHeatParam->chan] = ctlFrame->msgSrc;
                encap_purify_gram(ptrHeatParam->opcode,ptrHeatParam->chan,
            PURIFY_HEAT,
            &(ptrHeatParam->temperature),&canFrame);

            }
            else if(ctlFrame->opcode == PURIFY_TEMPERATURE)
            {
                temp_read_param * pstTempReadParam = &(ctlFrame->un_cmd.tempReadParam);
                unsigned int opcode = 0;
                int needReport = 0;
                int interv_ms = pstTempReadParam->interv;
                if(pstTempReadParam->isStart)
                {
                    opcode = CENTRE_START;
                    needReport = 1;
                }
                else
                {
                    opcode = CENTRE_STOP;
                    needReport = 0;
                    interv_ms = 0;
                }
                if(pstTempReadParam->chanNum >= MAX_PID_NUM)
                {
                    return;
                }
                purify_board_msg_src_heat[pstTempReadParam->chanNum] = ctlFrame->msgSrc;
                setTempReportCtl(CHAN_TEMP_SHAKE1,pstTempReadParam->chanNum,1000);
                encap_purify_gram(opcode,pstTempReadParam->chanNum,PURIFY_TEMPERATURE,
            &pstTempReadParam->interv,&canFrame);
                
            }
            else
            {  
                purifyCtl * ptrCtlData = &(ctlFrame->un_cmd.purifyCtlData);
                purify_board_msg_src_shake[ptrCtlData->chanNum] = ctlFrame->msgSrc;
                //if(ptrCtlData->paramType == PURIFY_SHAKE)
                encap_purify_gram(ctlFrame->opcode,ptrCtlData->chanNum,
            ptrCtlData->paramType,
            ptrCtlData,&canFrame);
            }
            

            
        }
        break;
        case SYSTEM_CTRL_BOARD:
        {
            djLiquidCtl * ptrCtlData = &(ctlFrame->un_cmd.djLiquidParam);

            encap_djctl_gram(ctlFrame->opcode,ptrCtlData->chanNum,
            ptrCtlData->paramType,&(ptrCtlData->duration),&canFrame);
        }
        break;
#else
        case QPCR_CTRL_BOARD:
        case QPCR_CTRL_BOARD_1:
        {
            int qpcrId = 0;
            if(QPCR_CTRL_BOARD == ctlFrame->sid)
            {
                qpcrId = 0;
            }
            else if(QPCR_CTRL_BOARD_1 == ctlFrame->sid)
            {
                qpcrId = 1;
            }
            if(ctlFrame->opcode==PURIFY_TEMPERATURE)
            {
                temp_read_param * pstTempReadParam = &(ctlFrame->un_cmd.tempReadParam);
                unsigned int opcode = 0;
                //int needReport = 0;
                int interv = pstTempReadParam->interv;
                int baseChanTemp = CHAN_TEMP_Q1_BASE;
                if(pstTempReadParam->isStart)
                {
                    opcode = CENTRE_START;
                    //needReport = 1;
                }
                else
                {
                    opcode = CENTRE_STOP;
                    interv = 0;
                    
                    //needReport = 0;
                }
                if(qpcrId)
                {
                    baseChanTemp = CHAN_TEMP_Q2_BASE;
                }
                printf("qpcr read temp, chan:%d,interv:%d\n",
                pstTempReadParam->chanNum,
                pstTempReadParam->interv);
                if(pstTempReadParam->chanNum == -1)
                {
                    setQpcrGrpReport(qpcrId,interv);
                }
                else
                {
                    //purify_board_msg_src_heat[pstTempReadParam->chanNum] = ctlFrame->msgSrc;
                    setTempReportCtl(CHAN_TEMP_SEAL_BASE,pstTempReadParam->chanNum,interv);
                }
                

                sendAckToLua(SUBBOARD_BASE+((ctlFrame->sid)<<5)+pstTempReadParam->chanNum,CHECK_MOVE_END);
            }
            else
            {
                if(ctlFrame->opcode==CENTRE_START)
                {
                    sendQpcrSheme(qpcrId,this);
                }

                if(ctlFrame->opcode==HEAT_CTL)
                {
                    encap_qpcr_gram_and_send(qpcrId,ctlFrame->opcode,&(ctlFrame->un_cmd.heatCtlData),this);
                    return;
                }
                encap_qpcr_gram_en(qpcrId, ctlFrame->opcode,&(ctlFrame->un_cmd.qpcrCtlData),&canFrame);
            }
            

        }
        break;
#endif
        case THERMAL_SEAL_BOARD:
        {
            printf("THERMAL_SEAL_BOARD, opcode:%d,msgSrc:%d\n",ctlFrame->opcode,
            ctlFrame->msgSrc);
            if(ctlFrame->opcode == HEAT_CTL)
            {
                if(ctlFrame->msgSrc == MSG_FROM_GRPC)
                {
                    heatParam * ptrHeatParam = &(ctlFrame->un_cmd.heatCtlData);
                    
                    //printf("");

                    encap_thermal_gram(ptrHeatParam->opcode,ptrHeatParam->chan,
                    THERMAL_HEAT,
                    &(ptrHeatParam->temperature),&canFrame);
                    sendAckToGrpc(0,0,60,-1);
                }
                else if(ctlFrame->msgSrc == MSG_FROM_LUA)
                {
                    heatParam * ptrHeatParam = &(ctlFrame->un_cmd.heatCtlData);
                    printf("seal board,op_ex:%d, op:%d,chan:%d\n",ctlFrame->opcode,
                    ptrHeatParam->opcode,
                    ptrHeatParam->chan);
                    //printf("");
                    if(ptrHeatParam->chan == SEAL_CHAN_SEAL
                      &&ptrHeatParam->opcode == CENTRE_START )
                    {
                        encap_thermal_gram_en(CENTRE_CONFIG,ptrHeatParam->chan,
                    THERMAL_HEAT,
                    &(ptrHeatParam->temperature),&canFrame);
                       
                    int bytesSend = this->WriteCanPort(&canFrame);
                    printf("send config, dlc:%d, %02x,%02x,%02x,sendbytes:%d\n",canFrame.can_dlc,canFrame.data[0],canFrame.data[1],canFrame.data[7],bytesSend);
                    usleep(2000);
                    }

                    encap_thermal_gram_en(ptrHeatParam->opcode,ptrHeatParam->chan,
                    THERMAL_HEAT,
                    &(ptrHeatParam->temperature),&canFrame);

                    sendAckToLua(SUBBOARD_BASE+(THERMAL_SEAL_BOARD<<5)+ptrHeatParam->chan,CHECK_MOVE_END);                    
                }          

            }
            else if(ctlFrame->opcode == PURIFY_TEMPERATURE)
            {
                temp_read_param * pstTempReadParam = &(ctlFrame->un_cmd.tempReadParam);
                unsigned int opcode = 0;
              //int needReport = 0;
              int interv = pstTempReadParam->interv;
                if(pstTempReadParam->isStart)
                {
                    opcode = CENTRE_START;
                    //needReport = 1;
                }
                else
                {
                    opcode = CENTRE_STOP;
                    interv = 0;
                    //needReport = 0;
                }
                printf("seal read temp, chan:%d\n",pstTempReadParam->chanNum);
                if(pstTempReadParam->chanNum >= MAX_PID_NUM)
                {
                    return;
                }
                //purify_board_msg_src_heat[pstTempReadParam->chanNum] = ctlFrame->msgSrc;
                setTempReportCtl(CHAN_TEMP_SEAL_BASE,pstTempReadParam->chanNum,interv);
                sendAckToLua(SUBBOARD_BASE+(THERMAL_SEAL_BOARD<<5)+pstTempReadParam->chanNum,CHECK_MOVE_END);

            }
        }
        break;
        case SCANCODE_BOARD:
        {
            if(ctlFrame->opcode == SCANCODE_CTL)
            {
                scancode_param * ptrScancodeParam = &(ctlFrame->un_cmd.scancodeParam);
                
                //printf("");
                int centreOpcode = ptrScancodeParam->isStart?CENTRE_START:CENTRE_STOP;
                encap_scancode_gram(centreOpcode,ptrScancodeParam->chanNum,
            SCANCODE_SCAN,
            NULL,&canFrame);

                recvDataEleCtl stLuaAckData;
                if(ctlFrame->msgSrc == MSG_FROM_LUA)
                {
                    if(ptrScancodeParam->chanNum<2)
                    {
                        stLuaAckData.frameType = CHECK_MOVE_END;
                        stLuaAckData.sid = SUBBOARD_BASE + (SCANCODE_BOARD<<5) + ptrScancodeParam->chanNum;
                        sendAckToLua(&stLuaAckData);
                    }
 
                }
                else
                {
                    sendAckToGrpc(0,0,61,-1);
                }

            }
        }
        break;
        default:
        break;
    }


    printf("send to sub board, canid is 0x%04x,opcode[%d]\n",canFrame.can_id,ctlFrame->opcode);
     printf("dlc:%d,",canFrame.can_dlc);
    for(int i=0;i<canFrame.can_dlc;i++)
    {
        printf("%02x,",canFrame.data[i]);
    }
    printf("\n");

    if(canFrame.can_dlc > 0)
    {
        this->WriteCanPort(&canFrame);
    }
    //send to ele ctl board.

}

int CCan::CanDataProcThreadFunc(void* lparam)
{
   CCan *pCan = (CCan*)lparam;
   struct can_frame tmpFrame;
   static int flagPrint = 0;
   while(1)
   {
        if( pCan->m_ExitThreadFlag )
	    {
		    break;
	    } 
        if(!pCan->m_recvFrameBuff.empty() )
        {
            memcpy(&tmpFrame,&pCan->m_recvFrameBuff.front(),sizeof(struct can_frame));
            pthread_mutex_lock(&mutex_recvBuff);
            pCan->m_recvFrameBuff.pop_front();
            pthread_mutex_unlock(&mutex_recvBuff);
#if _DEBUG_LOG
            printf("int dataProc thread, canid is <0x%08x>, dlc is %d\n",tmpFrame.can_id,tmpFrame.can_dlc); 
#endif
            //if((tmpFrame.can_id & MASK_RECV_UIM ) == MASK_RECV_UIM)
//             {
                
//                 uim_data recv_uim_data;

//                 if(CAN_EFF_FLAG&tmpFrame.can_id) //extented frame
//                 {
//                     int ret = parse_uim_data((void*)&tmpFrame,&recv_uim_data);
//                     if(ret == 0)
//                     {
//                     // printf("uim242 parse success\n");
//                         //print_uim_data(&recv_uim_data);
//                         pCan->PackagePro(&recv_uim_data);
//                     }
//                 }                
//                 else
//                 {
// #if _DEBUG_LOG
//                     printf("data is not from uim242 or data parse failed!\n");
// #endif
//                     pCan->PackagePro(&tmpFrame);
                    
//                 }
                
//             }
               pCan->PackagePro(&tmpFrame);
            //do parse and action here.
        }
        //msg_can_frame stMsgFrame;
        msg_ctl_uim ctlMsg;
        //stMsgFrame.type = 1;
        int lenRecv = msgrcv(pCan->getKeyId_FrameMQ(), &ctlMsg, sizeof(ctl_uim), pCan->getType_MQ(), IPC_NOWAIT);
        if(lenRecv>0)
        {
            printf("recv queue message\n");
            //pCan->WriteCanPort(&stMsgFrame.frame);
            //printf("opcode[%d],ele_num[%d]\n",ctlMsg.ctlFrame.opcode,ctlMsg.ctlFrame.ele_index);
            pCan->cmdAct(&(ctlMsg.ctlFrame));
        }
        if((lenRecv<0)&&(flagPrint == 0))
        {
            flagPrint = 1;
            perror("msgrcv in CanDataProcThreadFunc");
            printf("sizeof(ctl_uim):%d\n",sizeof(ctl_uim));
        }
        usleep(100);
   }
   printf( "CanDataProcThreadFunc finished\n");
   //pthread_exit( NULL );
   return 0;
}

void CCan::setKeyId_FrameMQ(int keyId)
{
    this->m_MQ_keyId = keyId;
}

int CCan::getKeyId_FrameMQ(void)
{
    return this->m_MQ_keyId;
}

int CCan::getType_MQ(void)
{
    return this->m_MQ_type;
}

void CCan::setType_MQ(int type)
{
    this->m_MQ_type = type;
}

void CCan::clearData(void)
{
    m_recvFrameBuff.clear();
}